package clocker

import (
	"fg-engine/queue/priority_queue"
	"time"
)

type ClockerFunc func()

// 时间粒度毫秒
type TimeEvent struct {
	expired_time int64
	interval     int64
	repeat_times int
	f            ClockerFunc
	stop         bool
}

func (m *TimeEvent) Less(other interface{}) bool {
	return m.expired_time < other.(*TimeEvent).expired_time
}

func (m *TimeEvent) Stop() {
	m.stop = true
}

type Clocker struct {
	queue *priority_queue.PriorityQueue
}

func New() *Clocker {
	p := &Clocker{}
	p.queue = priority_queue.New()
	return p
}

//params 间隔 | 重复次数 -1无限制 | 第一次执行时间 | 执行函数
func (m *Clocker) AddEvent(interval int, repeat int, first_expired_time int64, f ClockerFunc) *TimeEvent {
	e := &TimeEvent{}
	e.expired_time = first_expired_time
	e.interval = int64(interval)
	e.repeat_times = repeat
	e.f = f
	m.queue.Push(e)
	return e
}

func (m *Clocker) Second(t int, f ClockerFunc) *TimeEvent {
	return m.AddEvent(t*1000, -1, time.Now().Unix()*1000, f)
}

// 调整过 整分执行
func (m *Clocker) AdjustMinute(t int, f ClockerFunc) *TimeEvent {
	adjust := int64(60 - time.Now().Second())
	return m.AddEvent(60*1000*t, -1, time.Now().Unix()*1000+adjust*1000, f)
}

// 调整过 整点执行
func (m *Clocker) AdjustHour(f ClockerFunc) *TimeEvent {
	adjust := int64(3600 - (time.Now().Second() + time.Now().Minute()*60))
	return m.AddEvent(3600*1000, -1, time.Now().Unix()*1000+adjust*1000, f)
}

func (m *Clocker) Update() {
	cm := Getmseconds()

	for m.queue.Len() > 0 {
		v := m.queue.Top().(*TimeEvent)
		if v.expired_time > cm {
			break
		}
		m.queue.Pop()

		if v.stop {
			continue
		}
		v.f()

		if v.repeat_times != -1 {
			v.repeat_times--
			if v.repeat_times <= 0 {
				continue
			}
		}

		v.expired_time += v.interval
		m.queue.Push(v)
	}
}

// 获取今日凌晨时间戳
func GetTodayZeroHourTimestamp() int64 {
	now := time.Now()
	h := now.Hour()
	m := now.Minute()
	s := now.Second()
	return now.Unix() - int64(h*3600+m*60+s)
}

// 获取当前毫秒
func Getmseconds() int64 {
	return time.Now().UnixNano() / 1e6
}
